package Server;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.Query;
import General.ClientDetails;
import Messages.BadDetailsMsg;
import Messages.Msg;
import Messages.MsgType;
import Messages.StartConnectionMsg;
import Messages.StartMsg;
import Messages.StopMsg;
import ServerDB.User;

/**
 * this class is the thread that send the client all the data that 
 * he shares with other user, where the update is from the server, 
 * originate from other users
 * @author Liel && Guy
 */
public class SendToClientProtocol implements Runnable {
	Socket connection = null;
	ObjectOutputStream out;
	ObjectInputStream in;
	Msg response;
	Msg request;
	SendInfo server;
	ArrayList<Msg> messages;
	File file=new File("C:\\ourDropBox\\hibernate.cfg.xml");
	SessionFactory sessionFactory=new Configuration().configure(file).buildSessionFactory();
	org.hibernate.classic.Session sessionHibernate=sessionFactory.openSession();
	
	/**
	 * the constructor of the class
	 * @param connection - the socket
	 */
	public SendToClientProtocol(Socket connection){
		this.connection = connection;
		server = SendInfo.getInstance();
		messages = new ArrayList<Msg>();

	}

	public void run()
	{
		ClientDetails clientDetails=null;
		try{
			out = new ObjectOutputStream(connection.getOutputStream());
			out.flush();
			in = new ObjectInputStream(connection.getInputStream());
			//send start message to client
			request=new StartMsg();
			sendMessage(request);
			do
			{
				try
				{
					//get message from client
					response = (Msg)in.readObject();
					switch(response.getType())
					{
					//if this is start connection, the first message in conversation
					case START_CONNECTION:
						StartConnectionMsg startMsg = (StartConnectionMsg) response;
						clientDetails = new ClientDetails(startMsg.getUserName(), startMsg.getPassword(),
								startMsg.getMainFolder(), startMsg.getEmail(), null);
						//check if client is in the DB
						boolean isValid = IsUserValid(clientDetails);
						if (isValid){
							request=server.getMessage(clientDetails.getUserName());
						}
						else
							request = new BadDetailsMsg();
						sendMessage(request);
						break;
					//client send it to reveive message from server
					case WHITCH_ACTION:
						//get message to client
						request=server.getMessage(clientDetails.getUserName());
						sendMessage(request);
						break;
					
					}
				}

				catch(ClassNotFoundException classnot)
				{
					System.err.println("Data received in unknown format");
				}
			}while(request.getType()!=MsgType.STOP && request.getType()!=MsgType.BAD_DETAILS);
		}
		catch(IOException ioException)
		{
			ioException.printStackTrace();
		}
		finally
		{	
			//4: Closing connection
			try
			{
				Thread.sleep(1000);
				if (in!=null)
					in.close();
				if (out!=null)
					out.close();
			}
			catch(IOException ioException)
			{
				ioException.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	private void sendMessage(Msg msg)
	{
		if (msg==null){
			msg = new StopMsg();
		}
		try{
			out.writeObject(msg);
			out.flush();
			System.out.println("server>" + msg);
		}
		catch(IOException ioException){
			ioException.printStackTrace();
		}
	}
	//check if the user is valid
	private boolean IsUserValid(ClientDetails details){

		System.out.println("trying to validate user name and password");

		String strQueryUser1="FROM User";
		Query query1=sessionHibernate.createQuery(strQueryUser1);
		System.out.println("After SQL line");
		@SuppressWarnings("unchecked")
		List <User> listOfUsers=query1.list();


		String userName = details.getUserName();
		String password = details.getPassword();

		System.out.println("entered userName = "+userName+" and pass = "+password);

		for (User user : listOfUsers){
			System.out.println("user's userName = "+user.getUserName()+" and pass = "+user.getPassword());
			if (userName.equals(user.getUserName()) && password.equals(user.getPassword())){
				System.out.println("ret true");
				return true;
			}
		}
		System.out.println("ret false");
		return false;
	}
}
